package base

import (
	"context"
	"sync"
)

type (
	// IComponent 基础组件
	// 服务运行时的逻辑单元, 业务逻辑都应该抽象成一个个Component逻辑单元并赋予运行周期
	IComponent interface {
		Init(context.Context) // 初始化, 仅执行一次
		Start() error         // 启动, 仅执行一次
		Stop()                // 停止, 仅执行一次
		Suspend()             // 暂停, 可多次执行 todo 还不支持
		Resume()              // 继续, 可多次执行 todo 还不支持
		placeholderComponent()
	}

	// Component IComponent的基础实现
	Component struct {
		Ctx    context.Context    // 上下文
		Cancel context.CancelFunc // 上下文
		Wg     sync.WaitGroup     // 等待组
	}
)

// Init 提供默认的Init实现
// Component启用前会执行Init进行初始化
// 初始化应该尽量保持简单, 且应该认为此时的Component内的属性都是不可预料的, 不可直接使用
// 一般做一些简单的赋值操作, 或者直接使用此处默认的实现即可
func (c *Component) Init(ctx context.Context) {
	c.Ctx, c.Cancel = context.WithCancel(ctx)
}

// Start 初始化后就会执行Start启用Component, 通常用来做一些运行前的前置作业
func (c *Component) Start() error {
	return nil
}

// Stop 服务要结束时执行, 通常用来做一些的清理作业并保证graceful stop
func (c *Component) Stop() {
	c.Cancel()
	c.Wg.Wait()
}

// Suspend 服务暂停时执行, 可与Resume交替执行多次
// todo 等部署方案成熟后补充实现细节
func (c *Component) Suspend() {}

// Resume 服务暂停时执行, 可与Suspend交替执行多次
// todo 等部署方案成熟后补充实现细节
func (c *Component) Resume() {}

// AddDone 每个Component都提供WaitGroup用于执行计数器
// 按照约定, Component Stop时需要确保WaitGroup归零, 目的是用于graceful stop
func (c *Component) AddDone() func() {
	c.Wg.Add(1)

	return func() {
		c.Wg.Done()
	}
}

func (c *Component) placeholderComponent() {}
